#include "sql2.h"
#include <iostream>
#include <regex>
#include <vector>
#include "../mystr/mystr.h"

using namespace std;

class SqlParam
{
public:
    const char *type;
    const char *value;
    SqlParam(const char *t, const char *v) : type(t), value(v) {}
};

char *copy(const char *src, size_t count)
{
    char *dest = (char *)malloc((count + 1) * sizeof(char));
    strncpy(dest, src, count);
    *(dest + count) = 0;
    return dest;
}

size_t length(const char *src, const char *begin, const char *end)
{
    size_t count = 0;
    for (const char *i = begin; i < end; i++)
    {
        ++count;
    }
    return count;
}

vector<SqlParam> parse_sql_param(const char *src)
{
    regex null_pattern("^null((\\, )|$)");
    regex type_pattern("\\(([A-Z][A-Za-z]*)\\)((\\, )|)");
    cmatch null_match;
    cmatch type_match;

    vector<SqlParam> list;
    const char *begin = src;
    while (*begin)
    {
        if (regex_search(begin, null_match, null_pattern))
        {
            list.push_back(SqlParam("null", "null"));
            begin += null_match.position() + null_match.length();
        }
        else if (regex_search(begin, type_match, type_pattern))
        {
            list.push_back(SqlParam(type_match.str(1).c_str(),copy(begin, type_match.position())));
            begin += type_match.position() + type_match.length();
        }
        else
        {
            ++begin;
        }
    }
    return list;
}

char *to_sql(const char *src)
{
    if (*src)
    {
        const char *preparing_start = strstr(src, "==>  Preparing: ");
        const char *preparing_end = strchr(preparing_start, '\n');
        const char *parameters_start = strstr(preparing_end, "==> Parameters: ");
        if(preparing_start==nullptr||preparing_end==nullptr||parameters_start==nullptr)
        {
            return 0;
        }

        size_t preparing_length = strlen("==>  Preparing: ");
        size_t parameters_length = strlen("==> Parameters: ");

        vector<SqlParam> params = parse_sql_param(parameters_start + parameters_length);
        int i = 0;

        mystr result;
        for (const char *p = preparing_start + preparing_length; p != preparing_end; p++)
        {
            if (*p == '?')
            {
                if (strcmp("Integer", params[i].type) == 0 || strcmp("Long", params[i].type) == 0)
                {
                    result.append(params[i].value);
                }
                else
                {
                    result.append('\'');
                    result.append(params[i].value);
                    result.append('\'');
                }

                i++;
            }
            else
            {
                result.append(*p);
            }
        }

        return result.str();
    }
    return NULL;
}

int main()
{

    const char *src = R"(
2021-10-12 20:23:01.076 DEBUG 7648 --- [qtp613652233-34] m.s.e.m.BattleDataDao.queryBattleData    : ==>  Preparing: SELECT b.* FROM battle_data b INNER JOIN dictionary_target_type t ON b.fired_mblx=t.targetCode AND t.category=1 WHERE b.json_name=? AND b.fired_handle IN ( ? , ? , ? , ? , ? , ? , ? , ? , ? ) ORDER BY b.fired_handle,b.fire_handle
2021-10-12 20:23:01.076 DEBUG 7648 --- [qtp613652233-34] m.s.e.m.BattleDataDao.queryBattleData    : ==> Parameters: a(String), 2(Long), 3(Long), 19(Long), 4(Long), 36(Long), 5(Long), 6(Long), 7(Long), 26(Long)
    )";

    char *result = to_sql(src);
    std::cout << result << std::endl;
    return 0;
}